package avl.sv.shared;

import avl.sv.shared.model.classifier.AbstractClassifier;
import avl.sv.shared.model.featureGenerator.AbstractFeatureGenerator;
import java.awt.image.BufferedImage;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.jdesktop.swingx.treetable.DefaultMutableTreeTableNode;

public class Solution extends DefaultMutableTreeTableNode implements Serializable  {
    public String description = "";
    public int tileDim = 128;
    private ArrayList<AbstractClassifier> classifiers = new ArrayList<>();
    private ArrayList<AbstractFeatureGenerator> featureGenerators = new ArrayList<>();

    public ArrayList<AbstractFeatureGenerator> getFeatureGenerators() {
        return featureGenerators;
    }
    
    public boolean hasValidClassifier(){
        for(AbstractClassifier classifier:classifiers){
            if (classifier.isValid()){
                return true;
            }
        }
        return false;
    }
        
    public int getNumelFeatures(){
        int numelFeatures = 0;
        for (AbstractFeatureGenerator featureGenerator:featureGenerators){
            if (featureGenerator.isactive){
                numelFeatures += featureGenerator.getNumberOfFeatures();
            }
        }
        return numelFeatures;
    }
    
    public void getRequiredMemoryPerImage(int width, int height){
        
    }
    public void getAvalibleMemory(){
        
    }
    
    public double[][] getFeaturesForImages(List<Sample> samples){
        double features[][] = new double[samples.size()][getNumelFeatures()];
        BufferedImage imgs[] = new BufferedImage[samples.size()];
        for (int i = 0; i < samples.size(); i++){
            imgs[i] = samples.get(i).img;
        }
        int fIdx = 0;
        for (AbstractFeatureGenerator featureGenerator:featureGenerators){
            if (featureGenerator.isactive){
                double temp[][] = featureGenerator.getFeaturesForImages(imgs);
                if (temp.length != features.length){
                    throw new ArrayStoreException("Failure genererating features for sub images");
                }
                for (int i = 0; i < features.length; i++){
                    System.arraycopy(temp[i], 0, features[i], fIdx, featureGenerator.getNumberOfFeatures());
                }
            }
            fIdx += featureGenerator.getNumberOfFeatures();
        }
        return features;
    }

    public ArrayList<AbstractClassifier> getClassifiers() {
        return classifiers;
    }
       
    public Iterator<AbstractClassifier> getClassifierIterator(){
        return classifiers.iterator();
    }
    
    public Iterator<AbstractFeatureGenerator> getFeatureIterator(){
        return featureGenerators.iterator();
    }
    
    public int getNumelClassifiers(){
        return classifiers.size();
    }
    public int getNumelFeatureGenerators(){
        return featureGenerators.size();
    }
    
    public void trainClassifiers(ArrayList<SampleSetClass> samplesSets){
        for (AbstractClassifier classifier:classifiers){
            if (classifier.isActive()){
                classifier.train(samplesSets);
            }
        }
    }
    
    public void setClassifier(AbstractClassifier abstractClassifier ){
        for (AbstractClassifier classifier:classifiers){
            if (abstractClassifier.getClass() == abstractClassifier.getClass()){
                classifiers.remove(classifier);
                classifiers.add(abstractClassifier);
                return;
            }
        }
        classifiers.add(abstractClassifier);
    }
    
    public void setFeatureGenerator(AbstractFeatureGenerator abstractFeatureGenerator){
        for (AbstractFeatureGenerator featureGenerator:featureGenerators){
            if (abstractFeatureGenerator.getClass() == featureGenerator.getClass()){
                featureGenerators.remove(featureGenerator);
                featureGenerators.add(abstractFeatureGenerator);
                return;
            }
        }
        featureGenerators.add(abstractFeatureGenerator);
    }
    
    public void removeFeatureGenerator(Class c){
        for (AbstractFeatureGenerator featureGenerator:featureGenerators){
            if (c == featureGenerator.getClass()){
                featureGenerators.remove(featureGenerator);
                return;
            }
        }
    }
    
    public void removeClassifier(Class c){
        for (AbstractClassifier classifier:classifiers){
            if (c == classifier.getClass()){
                classifiers.remove(classifier);
                return;
            }
        }
    }
    
    public AbstractClassifier getClassifier(Class c){
        for (AbstractClassifier classifier:classifiers){
            if (c.isAssignableFrom(classifier.getClass())){
                return classifier;
            }
        }
        return null;
    }
    
    public AbstractFeatureGenerator getFeatureGenerator(Class c){
        for (AbstractFeatureGenerator featureGenerator:featureGenerators){
            if (c.isAssignableFrom(featureGenerator.getClass())){
                return featureGenerator;
            }
        }
        return null;
    }
    
    public Solution(String name) {
        super(name);       
    }
    
    public ArrayList<ClassifierClass> getClasses() {       
        if (children == null){
            return new ArrayList<>();
        }
        ArrayList<ClassifierClass> classifierClasses = new ArrayList<>();
        for (Object r:children){
            if (r instanceof ClassifierClass){
                classifierClasses.add((ClassifierClass)r);
            }
        }
        return classifierClasses;
    }
           
}

